package com.xiaoge.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xiaoge.auth.security.UserInfo;
import com.xiaoge.system.entity.Menu;
import com.xiaoge.system.entity.RoleMenu;
import com.xiaoge.system.mapper.MenuMapper;
import com.xiaoge.system.mapper.RoleMenuMapper;
import com.xiaoge.system.service.MenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author xiaoge
 * @since 2021-02-02
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private RoleMenuMapper roleMenuMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 根据角色获取菜单列表
     *
     * @return
     */
    @Override
    public List<Menu> getMenusWithRole() {
        return menuMapper.getMenusWithRole();
    }

    /**
     * 根据用户id获取菜单
     *
     * @return
     */
    @Override
    public List<Menu> getMenusByAdminId() {
        Long adminId = ((UserInfo) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId();
        ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
        List<Menu> menus = (List<Menu>) valueOperations.get("menus_" + adminId);
        if (CollectionUtils.isEmpty(menus)) {
            menus = menuMapper.getMenusByAdminId(adminId);
            valueOperations.set("menus_" + adminId, menus);
        }
        return menus;
    }

    /**
     * 查询所有菜单
     *
     * @return
     */
    @Override
    public List<Menu> getAll() {
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
        List<Menu> menus = (List<Menu>) valueOperations.get("menus_all");
        if (CollectionUtils.isEmpty(menus)) {
            menus = menuMapper.selectList(queryWrapper);
            valueOperations.set("menus_all", menus);
        }
        return menus;
    }

    /**
     * 添加菜单
     *
     * @param menu
     */
    @Override
    public void add(Menu menu) {
        menu.setOpen(0);
        menuMapper.insert(menu);
    }

    /**
     * 修改菜单
     *
     * @param menu
     */
    @Override
    public void updateMenu(Menu menu) {
        menuMapper.updateById(menu);
        //清除所有菜单redis缓存
        Set<String> keys = redisTemplate.keys("menus_" + "*");
        redisTemplate.delete(keys);
    }

    /**
     * 删除菜单
     *
     * @param menuId
     */
    @Override
    public void delMenu(Long menuId) {
        menuMapper.deleteById(menuId);
        QueryWrapper<RoleMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("menu_id", menuId);
        roleMenuMapper.delete(queryWrapper);
        //清除所有菜单redis缓存
        Set<String> keys = redisTemplate.keys("menus_" + "*");
        redisTemplate.delete(keys);
    }


    /**
     * 构建menuTree
     *
     * @return
     */
    @Override
    public List<Menu> menuTreeBuild(List<Menu> menus) {
        if (menus.size() == 0) {
            throw new Error("未查询到菜单信息");
        }
        //主菜单
        List<Menu> menuList = new ArrayList<>();
        //子菜单
        List<Menu> subMenuList = new ArrayList<>();
        //具体菜单项
        List<Menu> itemList = new ArrayList<>();

        //分类菜单的位置，
        for (Menu menu : menus) {
            if (menu.getParentId() == 0) {
                menuList.add(menu);
            } else if (menu.getParentId() != 0 && menu.getType().equals("0") && (menu.getUrl() == null || menu.getUrl().equals(""))) {
                subMenuList.add(menu);
            } else if (menu.getParentId() != 0 && menu.getType().equals("1") && menu.getUrl() != null) {
                itemList.add(menu);
            }
        }

        //子菜单组合到主菜单
        for (Menu menu : subMenuList) {
            findSubMenu(menuList, menu);
        }

        //具体菜单项组合到子菜单
        for (Menu menu : itemList) {
            findSubMenu(menuList, menu);
        }

        //排序
        sortSubMenu(menuList);
        return menuList;
    }

    /**
     * permsTree构建
     *
     * @param menus
     * @return
     */
    @Override
    public List<Menu> permsTreeBuild(List<Menu> menus) {
        if (menus.size() == 0) {
            throw new Error("未查询到菜单信息");
        }
        //主菜单
        List<Menu> menuList = new ArrayList<>();
        //子菜单
        List<Menu> subMenuList = new ArrayList<>();
        //具体菜单项
        List<Menu> itemList = new ArrayList<>();
        //权限集合
        List<Menu> permsList = new ArrayList<>();

        //分类菜单的位置，
        for (Menu menu : menus) {
            if (menu.getParentId() == 0) {
                menuList.add(menu);
            } else if (menu.getParentId() != 0 && menu.getType().equals("0") && (menu.getUrl() == null || menu.getUrl().equals(""))) {
                subMenuList.add(menu);
            } else if (menu.getParentId() != 0 && menu.getType().equals("1") && menu.getUrl() != null) {
                itemList.add(menu);
            } else if (menu.getParentId() != 0 && menu.getType().equals("2")) {
                permsList.add(menu);
            }
        }
        //按钮组合到目录
        for (Menu menu : permsList) {
            findSubMenu(itemList, menu);
        }

        //目录组合到子菜单
        for (Menu menu : itemList) {
            findSubMenu(subMenuList, menu);
        }

        //目录组合到主菜单
        for (Menu menu : itemList) {
            findSubMenu(menuList, menu);
        }

        //子菜单组合到主菜单
        for (Menu menu : subMenuList) {
            findSubMenu(menuList, menu);
        }

        //返回对应菜单树并排序
        if (menuList.size()!=0&&subMenuList.size()!=0){
            sortSubMenu(menuList);
            return menuList;
        }else if (subMenuList.size()!=0){
            sortSubMenu(subMenuList);
            return subMenuList;
        }else if (itemList.size()!=0){
            itemList.addAll(menuList);
            sortSubMenu(itemList);
            return itemList;
        }else if (permsList.size()!=0){
            sortSubMenu(permsList);
            return permsList;
        }
        return menuList;
    }

    //递归将子菜单组合到父菜单的children中
    private void findSubMenu(List<Menu> menus, Menu item) {
        for (Menu menu : menus) {
            if (item.getParentId().equals(menu.getId())) {
                menu.add(item);
            } else if (menu.getChildren().size() > 0) {
                findSubMenu(menu.getChildren(), item);
            }
        }
    }

    //递归将children中的数据排序
    private void sortSubMenu(List<Menu> menus) {
        menus.sort(Menu.order());
        for (Menu menu : menus) {
            if (menu.getChildren().size()>0){
                sortSubMenu(menu.getChildren());
            }
        }
    }
}
